"""
Contains top level panels for the panelbar.
Written By: Daniel Ortiz
"""
import os, mimetypes
import wx
import wx.lib.foldpanelbar as fpb
from text import MailText
from database.mapclass import *

class HeaderPanel(wx.Panel):
    """The header panel contains the message header"""
    def __init__(self, parent):
        self.parent = parent
        wx.Panel.__init__(self, parent)
        self.CreateLayout()
        self.BindEvents()
        self.Variables()
        
    def Variables(self):
        """Class-wide variables"""
        self.text_to_ctrl = {"to" : self.to_text, "cc" : self.cc_text, "bcc" : self.bcc_text}
        
    def CreateLayout(self):
        """Creates the layout for the panel"""
        sizer = wx.GridBagSizer(hgap = 1, vgap = 1)
        fromt = wx.StaticText(self, -1,'From: ')
        self.from_text = MailText(self)
        tot = wx.StaticText(self,-1, 'To: ')
        self.to_text = MailText(self)
        cct = wx.StaticText(self,-1, 'Cc: ')
        self.cc_text = MailText(self)
        bcct = wx.StaticText(self,-1, 'Bcc: ')
        self.bcc_text = MailText(self)
        subjectt = wx.StaticText(self,-1, 'Subject: ')
        self.subject_text = MailText(self)
        self.subject_text.Bind(wx.EVT_KILL_FOCUS, self.UpdateSubject)
        self.text = [self.from_text, self.to_text, self.cc_text, self.bcc_text, self.subject_text]
        
        sizer.Add(fromt, pos = (0, 0))
        sizer.Add(self.from_text, pos = (0, 1), span =  (1, 12), flag = wx.EXPAND)
        sizer.Add(tot, pos = (1, 0))
        sizer.Add(self.to_text, pos = (1, 1), span = (1, 12), flag = wx.EXPAND)
        sizer.Add(cct, pos = (2, 0))
        sizer.Add(self.cc_text, pos = (2, 1), span = (1, 12), flag = wx.EXPAND)
        sizer.Add(bcct, pos = (3, 0))
        sizer.Add(self.bcc_text, pos = (3, 1), span = (1, 12), flag = wx.EXPAND)
        sizer.Add(subjectt, pos = (4, 0))
        sizer.Add(self.subject_text, pos = (4, 1), span = (1, 12), flag = wx.EXPAND)
        sizer.AddGrowableCol(10)
        self.SetSizer(sizer)
        self.Fit()
        
    def BindEvents(self):
        """Bind global events to the panel"""
        self.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption)
        
    def OnPressCaption(self, event):
        """Continue the progression of the Caption Bar Event"""
        event.Skip()
        
    def ResizeWithRect(self, rect):
        """Resize the text ctrl in the window"""
        self.SetRect(rect)
        for t in self.text:
            pos = t.GetPosition()
            t.SetSize((rect[2] - pos[0], -1))

    def Add(self, mail):
        """Add the mail header to the panel"""
        self.from_text.SetValue(mail.from_who or '')
        self.to_text.SetValue(mail.to or '')
        self.bcc_text.SetValue(mail.bcc or '')
        self.cc_text.SetValue(mail.cc or '')
        self.subject_text.SetValue(mail.subject or '')
        
    def Clear(self):
        """Clear the panel to its initial state"""
        self.from_text.SetValue('')
        self.to_text.SetValue('')
        self.bcc_text.SetValue('')
        self.cc_text.SetValue('')
        self.subject_text.SetValue('')
        
    def GetData(self):
        """Return the data of the panel"""
        ret = {}
        ret['From'] = self.from_text.GetValue()
        ret['To'] = self.to_text.GetValue()
        ret['Bcc'] = self.bcc_text.GetValue()
        ret['Cc'] = self.cc_text.GetValue()
        ret['Subject'] = self.subject_text.GetValue()
        return ret
    
    def AppendData(self, text, data):
        """text - To, Bcc, Cc, data - the string to append to the relevant textctrl"""
        if self.text_to_ctrl.has_key(text):
            text_ctrl = self.text_to_ctrl[text]
            if text_ctrl.GetValue():
                text_ctrl.AppendText(" , " + data)
            else:
                text_ctrl.AppendText(data)
    
    def UpdateSubject(self, event):
        """Update the subject on the panel"""
        h = self.GetTopLevelParent()
        p = h.splitter_window.mail_notebook
        p.SetPageText(p.GetIndex(), self.subject_text.GetValue()[:p.length])

class AttachList(wx.ListCtrl):
    """The attach list contains a list of attachments"""
    def __init__(self, parent):
        self.parent = parent
        wx.ListCtrl.__init__(self, parent, style = wx.LC_REPORT)
        self.ClassVariables()
        self.CreateColumns()
        self.BindEvents()
        
    def ClassVariables(self):
        """Instantiate all of the class wide variables"""
        self.resize = False
        self.attach = []
        self.columns = ['Name', 'Type', 'Size']

    def CreateColumns(self):
        """Function draws and creates the columns of the Tree List"""
        for col, text in enumerate(self.columns):
            self.InsertColumn(col, text)
            
    def BindEvents(self):
        """Function binds the MailList to all relevant wx events"""
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_IDLE, self.OnIdle)
        self.parent.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self)
        
    def OnSize(self, event):
        """Resize the window"""
        self.resize = True
        event.Skip()
        
    def OnIdle(self, event):
        """Will resize the window when the window gets an idle event"""
        if self.resize:
            size = self.parent.GetSize()
            for col, text in enumerate(self.columns):
                self.SetColumnWidth(col, (size[0] - 1) / len(self.columns))
            self.Refresh()
            self.resize = False
    
    def OnItemSelected(self, event):
        """Save the selected item"""
        if self.attach:
            cattach = self.attach[event.m_itemIndex]
            dlg = wx.FileDialog(self, 'Choose a file', defaultDir = os.getcwd(),
                                style = wx.SAVE)
            if dlg.ShowModal() == wx.ID_OK:
                path = dlg.GetPath()
                if path:
                    fd = open(path, 'w')
                    fd.write(cattach.data)
                    fd.close()
            dlg.Destroy()
            
    def Add(self, attach):
        """Add the attachments to the current list"""
        self.attach = self.attach + attach
        for a in attach:
            size = "%d bytes" % a.size
            self.Append([a.title, a.encoding, size])
            
    def Clear(self):
        """Clear everything in the list"""
        self.DeleteAllItems()
        self.attach = []
            
class AttachmentPanel(wx.Panel):
    """Attachment panel is the gui interface for attachments"""
    def __init__(self, parent):
        self.parent = parent
        wx.Panel.__init__(self, parent)
        self.CreateLayout()
        self.Variables()
        
    def CreateLayout(self):
        """Create layout for the panel"""
        self.attach_path = MailText(self)
        self.attach_button = wx.Button(self, -1, "Attach")
        self.Bind(wx.EVT_BUTTON, self.OnAttach, self.attach_button)
        self.attach_list = AttachList(self)
        self.attach = [self.attach_path, self.attach_list]
        sizer = wx.GridBagSizer(hgap = 1, vgap = 1)
        sizer.Add(self.attach_button, pos = (0, 0))
        sizer.Add(self.attach_path, pos = (0, 1), span = (1, 11), flag = wx.EXPAND)
        sizer.Add(self.attach_list, pos = (1, 0), span = (7, 12), flag = wx.EXPAND)
        sizer.AddGrowableCol(10)
        self.SetSizer(sizer)
        self.Fit()
        
    def Variables(self):
        """Class wide variables"""
        self.IsDraft = False
        
    def ResizeWithRect(self, rect):
        """Resize the text ctrl in the window"""
        self.SetRect(rect)
        for t in self.attach:
            pos = t.GetPosition()
            t.SetSize((rect[2] - pos[0], -1))
            
    def Add(self, attach):
        """Add the attachments to the current list"""
        self.attach_list.Add(attach)
    
    def CreateAttachment(self, buf, path):
        """Create the attachment from the user input and add it to the mail"""
        self.IsDraft = True
        t = mimetypes.guess_type(path)
        att = Attachment(os.path.basename(path), buf, len(buf), t[0])
        self.attach_list.Add([att])
    
    def OnAttach(self, event):
        """Attach a user specified file to the mail"""
        self.NewAttach()
    
    def NewAttach(self):
        """Create a new attachment interface"""
        dlg = wx.FileDialog(self, 'Choose a file', defaultDir = os.getcwd(),
                            style = wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            if path:
                fd = open(path, 'r')
                buf = fd.read()
                fd.close()
                self.CreateAttachment(buf, path)
        dlg.Destroy()
        
    def SaveAttachments(self):
        """Save the current attachments of the panel"""
        dialog = wx.DirDialog(self, "Choose a directory:", style  = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dialog.ShowModal() == wx.ID_OK:
            path = dialog.GetPath()
            for att in self.attach_list.attach:
                fd = open(path + '/' + att.title, 'w')
                fd.write(att.data)
                fd.close()
        dialog.Destroy()
        
    def Clear(self):
        """Clear the panel"""
        self.attach_path.SetValue('')
        self.attach_list.Clear()
        self.ClearFlags()
        
    def ClearFlags(self):
        """Clear the relevant state flags of the panel"""
        self.IsDraft = False
        
    def GetData(self):
        """Returns the attachment data"""
        return self.attach_list.attach